using System;
using System.Collections.Generic;
using System.Reflection;

namespace Sagile.Nepma
{
    /// <summary>
    /// <see cref="TaskLoader"/> exposes methods to search for tasks (class inheriting <see cref="TaskBase"/>) and return instances of those.
    /// </summary>
    public static class TaskLoader
    {
        /// <summary>
        /// Gets <see cref="TaskManager"/> from assembly. All subclasses of <see cref="TaskBase"/> in the given assembly are loaded as tasks into the newly created <see cref="TaskManager"/>.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <returns></returns>
        public static TaskManager GetTaskManagerFromAssembly(Assembly assembly)
        {
            TaskManager manager = new TaskManager();
            manager.AddGroup(GetTasksFromAssembly(assembly));

            return manager;
        }

        /// <summary>
        /// Gets the tasks from the specified assembly. This method looks for all subclasses of <see cref="TaskBase"/>, and return a array contains an instance of each.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <returns></returns>
        public static TaskBase[] GetTasksFromAssembly(Assembly assembly)
        {
            Type[] taskTypes = GetSubClasses(assembly, typeof(TaskBase));

            List<TaskBase> tasks = new List<TaskBase>();
            foreach (Type aType in taskTypes)
            {
                TaskBase task = Activator.CreateInstance(aType) as TaskBase;
                tasks.Add(task);
            }
            tasks.Sort();
            return tasks.ToArray();
        }

        /// <summary>
        /// Gets the subclasses of a given <see cref="Type"/>.
        /// </summary>
        /// <param name="asm">The assembly.</param>
        /// <param name="baseClassType">Type of the base class.</param>
        /// <returns></returns>
        private static Type[] GetSubClasses(Assembly asm, Type baseClassType)
        {
            List<Type> subClasses = new List<Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.IsSubclassOf(baseClassType))
                {
                    subClasses.Add(type);
                }
            }
            return subClasses.ToArray();
        }
    }
}
